package com.ether.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.AbstractCellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.*;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExcelUtil {

    /**
     * 通用Excel导出方法
     */
    public static <T> void export(
            HttpServletResponse response,
            String fileName,
            String sheetName,
            List<T> data,
            Class<T> clazz
    ) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20") + ".xlsx";
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);

        EasyExcel.write(response.getOutputStream(), clazz)
                .registerWriteHandler(new CustomCellStyleStrategy()) // 注册样式处理器
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自动列宽
                .sheet(sheetName)
                .doWrite(data);
    }

    /**
     * 自定义单元格样式策略 - 修复版
     */
    public static class CustomCellStyleStrategy extends AbstractCellWriteHandler {

        @Override
        public int order() {
            return 80000;
        }

        // 缓存样式对象，提高性能
        private final Map<String, CellStyle> styleCache = new HashMap<>();

        @Override
        public void afterCellDispose(WriteSheetHolder writeSheetHolder,
                                     WriteTableHolder writeTableHolder,
                                     List<WriteCellData<?>> cellDataList,
                                     Cell cell,
                                     Head head,
                                     Integer relativeRowIndex,
                                     Boolean isHead) {

            Workbook workbook = writeSheetHolder.getSheet().getWorkbook();

            // 生成样式缓存键
            String styleKey = generateStyleKey(isHead, cell.getColumnIndex(), cell.getRowIndex());

            // 获取或创建样式
            CellStyle cellStyle = styleCache.computeIfAbsent(styleKey, k ->
                    createCellStyle(workbook, isHead, cell.getColumnIndex(), cell.getRowIndex())
            );

            // 应用样式到单元格
            cell.setCellStyle(cellStyle);
        }

        /**
         * 生成样式缓存键
         */
        private String generateStyleKey(boolean isHead, int columnIndex, int rowIndex) {
            if (isHead) {
                return "HEADER_" + columnIndex;
            } else {
                return "DATA_" + columnIndex + "_" + (rowIndex % 2); // 区分奇偶行
            }
        }

        /**
         * 创建单元格样式
         */
        private CellStyle createCellStyle(Workbook workbook, boolean isHead, int columnIndex, int rowIndex) {
            CellStyle style = workbook.createCellStyle();

            // 设置通用样式
            setCommonStyle(style);

            if (isHead) {
                setHeaderStyle(workbook, style);
            } else {
                setDataCellStyle(workbook, style, columnIndex);

                // 斑马纹效果（可选）
                if (rowIndex % 2 == 1) {
                    style.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
                    style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                }
            }

            return style;
        }

        /**
         * 设置通用样式
         */
        private void setCommonStyle(CellStyle style) {
            // 设置边框
            style.setBorderTop(BorderStyle.THIN);
            style.setBorderBottom(BorderStyle.THIN);
            style.setBorderLeft(BorderStyle.THIN);
            style.setBorderRight(BorderStyle.THIN);

            // 设置对齐方式
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);
        }

        /**
         * 设置表头样式
         */
        private void setHeaderStyle(Workbook workbook, CellStyle style) {
            Font font = workbook.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 16);
            font.setColor(IndexedColors.WHITE.getIndex());

            style.setFont(font);
            style.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex());
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        }

        /**
         * 设置数据单元格样式
         */
        private void setDataCellStyle(Workbook workbook, CellStyle style, int columnIndex) {
            Font font = workbook.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 14);

            style.setFont(font);

            DataFormat dataFormat = workbook.createDataFormat();

            // 根据列索引设置不同的数据格式
            switch (columnIndex) {
                case 0: // 文本格式
                    style.setDataFormat(dataFormat.getFormat("@"));
                    break;
                case 1: // 整数格式
                    style.setDataFormat(dataFormat.getFormat("0"));
                    break;
                case 2: // 文本格式（防止科学计数法）
                    style.setDataFormat(dataFormat.getFormat("@"));
                    break;
                case 3: // 货币格式
                    style.setDataFormat(dataFormat.getFormat("¥#,##0.00"));
                    break;
                case 4: // 日期格式
                    style.setDataFormat(dataFormat.getFormat("yyyy-mm-dd"));
                    break;
                default:
                    style.setDataFormat(dataFormat.getFormat("General"));
                    break;
            }
        }
    }
}